package com.ruoyi.cmdb.controller;

import com.ruoyi.cmdb.domain.Auth;
import com.ruoyi.cmdb.util.ExecShell;
import com.ruoyi.cmdb.vo.ExecShellRes;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteWatchdog;
import org.apache.commons.exec.PumpStreamHandler;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.*;
import java.util.List;

/**
 * 测试java执行shell
 *
 */
@RestController
@RequestMapping("/cmdb/testJavaExecShell")
@Api(tags = "1.testJavaExecShell")
public class TestJavaExecShellController {
    /**
     * testJavaExecShell ByApacheCommondExec
     */
    @GetMapping("/ByApacheCommondExec")
    @ApiOperation("ByApacheCommondExec")
    public AjaxResult ByApacheCommondExec()  {

        try {
            CommandLine commandLine = CommandLine.parse("ls -l"); //使用它需要引入外部依赖
            DefaultExecutor executor = new DefaultExecutor();

            executor.setWatchdog(new ExecuteWatchdog(60000));//set timeout

            final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            final ByteArrayOutputStream errorStream = new ByteArrayOutputStream();

            PumpStreamHandler streamHandler = new PumpStreamHandler(new PrintStream(outputStream), new PrintStream(errorStream));
            executor.setStreamHandler(streamHandler);

            int exitCode = executor.execute(commandLine);

            String output = outputStream.toString();
            try (BufferedReader reader = new BufferedReader(new StringReader(output))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    if (line.contains("sql")) {
                        System.out.println(line);
                    }
                }
            }

            String error = errorStream.toString();
            if (!error.isEmpty()) {
                System.err.println("Command error:");
                System.err.println(error);
            }


            if (exitCode == 0) {
                System.out.println("Command executed successfully.");
            } else {
                System.out.println("Command execution failed with exit code: " + exitCode);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("ByApacheCommondExec success sout");
        return AjaxResult.success("ByApacheCommondExec success");
    }

    //use runtime.exec() exec shell commond
    /**
     * testJavaExecShell ByRuntime
     */
    @GetMapping("/ByRuntime")
    @ApiOperation("ByRuntime")
    public AjaxResult ByRuntime()  {
        try {
            Process process = Runtime.getRuntime().exec("ls a.txt");
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }

            BufferedReader error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            if ((line = error.readLine()) != null){
                System.out.println("sout error:");
                while ((line = error.readLine()) != null) {
                    System.out.println(line);
                }
            }
            // 等待命令执行完成
            int exitCode = process.waitFor();
            System.out.println("Exited with code : " + exitCode);

        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(1111111111);
        return AjaxResult.success("执行成功");

    }

    //use processBuilder exec shell commond
    /**
     * testJavaExecShell ByProcessBuilder
     */
    @GetMapping("/ByProcessBuilder")
    @ApiOperation("ByProcessBuilder")
    public AjaxResult ByProcessBuilder()  {
        try {
            ProcessBuilder processBuilder = new ProcessBuilder("ls", "a.txt"); //好处是,允许你设置命令的各个部分，而不是将整个命令作为一个字符串传递，这避免了shell注入攻击的风险。
            Process process = processBuilder.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            reader.close();
            BufferedReader error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            if ((line = error.readLine()) != null){
                System.out.println("sout error:");
                while ((line = error.readLine()) != null) {
                    System.out.println(line);
                }
            }
            error.close();
            int exitCode = process.waitFor();
            System.out.println("Exited with code: " + exitCode);

        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(1111111111);
        return AjaxResult.success("执行成功");
    }

    /**
     * testJavaExecShell ByExecShell
     */
    @GetMapping("/ByExecShellObject")
    @ApiOperation("ByExecShellObject")
    public AjaxResult ByExecShellObject()  {
        BufferedReader output;
        BufferedReader error;
        Integer exitCode;
        String line = null;

        //ExecShellRes execShellRes=ExecShell.ByApacheCommondExec("ls -l"); //这3个方法都可以无差别执行shell
        //ExecShellRes execShellRes=ExecShell.ByRuntime("ls -l");           //这3个方法都可以无差别执行shell
        ExecShellRes execShellRes=ExecShell.ByProcessBuilder("ls -l");      //这3个方法都可以无差别执行shell
        output=execShellRes.getOutput();

        while (true) {
            try {
                if (!((line = output.readLine()) != null)) break;
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (line.contains("sql")) {
                System.out.println(line);
            }
        }



        error=execShellRes.getError();
        while (true) {
            try {
                if (!((line = error.readLine()) != null)) break;
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println(line);
        }

        exitCode=execShellRes.getExitCode();
        if (exitCode != 0) {
            System.out.println("Command execution failed with exit code: " + exitCode);
        }

        System.out.println("ByExecShellObject success sout");
        return AjaxResult.success("ByExecShellObject success");
    }
}
